import { filterObj } from '@/utils'
import type { RouteRecordRaw, RouteMeta } from 'vue-router'

type Context = {
  default: RouteItem[]
}
/**
 * 根据comPath或者name返回() => import(path)
 */
function handleCom(item: RouteItem, keyPath: string) {
  keyPath = keyPath.replace('/src', '..')
  keyPath = keyPath.replace('/route.ts', '')
  let path = ''
  if (item.comPath) {
    if (item.comPath.startsWith('./')) {
      path = keyPath + item.comPath.slice(1) // 去掉.
    } else if (item.comPath.startsWith('../')) {
      const len1 = Number(item.comPath.match(/\.\.\//g)?.length)
      const len2 = keyPath.split('/').slice(1, -len1)
      if (len2.length) {
        len2.unshift('..')
        path = len2.join('/') + '/' + item.comPath.replaceAll('../', '')
      }
      throw new Error(`${item.title} 路由中的comPath格式不正确`)
    } else if (item.comPath.startsWith('@/views/')) {
      path = item.comPath.replace('@', '../')
    } else {
      throw new Error(`${item.title} 路由中的comPath格式不规范`)
    }
  } else {
    path = `${keyPath}/${item.name}/index.vue`
  }
  return () => {
    console.log(path)

    return import(path)
  }
}
/**
 * 寻找判断子路由，给children添加数据
 */
function lookChildRoute(
  obj: RouteRecordRaw,
  item: RouteItem,
  context: Record<string, Context>,
  keyPath: string,
  parentPath: string,
) {
  const pathArr = keyPath.split('/')
  if (item.comPath) {
    if (item.comPath.startsWith('./')) {
      keyPath = keyPath.replace('/route.ts', '') + item.comPath.slice(1)
      if (context[keyPath]) obj.children = computedRoute(keyPath, context, parentPath)
    } else if (item.comPath.startsWith('../')) {
      return
    } else if (item.comPath.startsWith('@/views/')) {
      keyPath = item.comPath.replace('@', '/src')
      if (context[keyPath]) obj.children = computedRoute(keyPath, context, parentPath)
    }
  } else {
    pathArr.splice(-1, 0, item.name)
    keyPath = pathArr.join('/')
    if (context[keyPath]) obj.children = computedRoute(keyPath, context, parentPath)
  }
}

function computedRoute(keyPath: string, context: Record<string, Context>, parentPath = ''): RouteRecordRaw[] {
  return context[keyPath].default.map((item) => {
    if (parentPath === '/') parentPath = ''
    const path = item.path ? item.path : parentPath + '/' + item.name
    const obj: RouteRecordRaw = {
      path,
      name: item.name,
      redirect: item.redirect,
      meta: {
        title: item.title,
        hidden: item.hidden,
        icon: item.icon,
        rank: item.rank,
        subMenu: item.subMenu,
        keepAlive: item.keepAlive,
        id: item.id,
      },
      children: [],
    }
    if (!item.subMenu) obj.component = handleCom(item, keyPath)
    obj.meta = filterObj(obj.meta as RouteMeta)

    lookChildRoute(obj, item, context, keyPath, path)

    return filterObj(obj) as RouteRecordRaw
  })
}
/**
 * 根据views目录下的route.ts生成路由表
 */
export function genRouters(): RouteRecordRaw[] {
  /*
    两种错误情况：
      1、忘记在上级route.ts配置
      2、中间间隔了一层没有route.ts
      3、有配置但是没有文件
    需要考虑name重复问题，重复直接抛错

    几个有作用的key，name,comPath

    得到import(path)
    import(path)中的path要全部变成'../views/....../index.vue'格式
    先判断comPath：{
      ./开头直接连接
      ../开头splice再连接
      @/views/开头，把@/views/替换成../views/，如果不是以@/views/开头，则抛错
    }
    没有comPath，判断name: 直接连接name

    判断子路由
    先判断comPath：{
      ./开头直接连接，通过context[key]得到子路由
      ../开头，不符合规则，直接判定没有子路由
      @/views/开头，把@/views/替换成../views后，比较和./开头的格式，不相等则直接判定没有子路由，不符合规则
    }
    判断name: 直接连接name，通过context[key]得到子路由
  */

  const context = import.meta.glob<true, string, Context>(['@/views/**/route.ts'], { eager: true })
  // 从顶级路由开始计算
  const routes = computedRoute('/src/views/route.ts', context)
  console.log(routes)

  return routes
}
